var minWindow = function (s, t) {
  // 双指针
  let l = 0;
  let r = 0;
  // 创建字典,维护t中元素和元素的长度
  const need = new Map();
  for (const c of t) {
    need.set(c, need.has(c) ? need.get(c) + 1 : 1);
  }
  // 需要的类型数量
  let needType = need.size;
  let res = '';

  while (r < s.length) {
    // 获取右指针当前的字符
    const c = s[r];
    // 右指针的元素在当前的need列表中
    if (need.has(c)) {
      need.set(c, need.get(c) - 1);
      if (need.get(c) === 0) needType -= 1;
    }
    // 当 needType 为零时，意味着当前滑动窗口中包含了所有 t 中的字符
    // 通过收缩左指针的位置来寻找最短的子串。在这个循环中，我们不断地收缩左指针 l，直到 needType 不为零
    while (needType === 0) {
      const newRes = s.substring(l, r + 1);
      if (!res || newRes.length < res.length) res = newRes;
      const c2 = s[l];
      if (need.has(c2)) {
        need.set(c2, need.get(c2) + 1);
        // 恰好为 1（意味着此时窗口不再包含目标字符 c2，所以 needType 需要加一）
        if (need.get(c2) === 1) needType += 1;
      }
      l += 1;
    }
    r += 1;
  }
  return res;
};
